<template>
  <div class="main">
    <div ref="chatLeft" class="chat-left" :style="{ width: leftWidth + 'px' }">
      <div class="contract">
        <p v-show="leftWidth >= fixedWidth" class="contract_title">源端信息</p>
        <div
          class="svg_box"
          :style="{
            transform: leftWidth >= fixedWidth ? '' : 'rotate(180deg)',
          }"
          @click="handleChangeLeftWidth"
        >
          <svg
            width="20"
            height="20"
            viewBox="0 0 17 17"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <g opacity="0.6">
              <path
                d="M5.35156 8.5H15.3516"
                stroke="#333333"
                stroke-width="1.5"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <path
                d="M9.09347 13.1559L4.4375 8.49981L9.09347 3.84375"
                stroke="#333333"
                stroke-width="1.5"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <rect
                x="0.351562"
                y="2.5"
                width="1.5"
                height="12"
                rx="0.75"
                fill="#333333"
              />
            </g>
          </svg>
        </div>
      </div>
      <ul
        v-if="leftWidth >= fixedWidth && databaseInfoValue.source"
        class="database_info"
      >
        <li>
          <span class="database_info-title">任务类型：</span><span class="database_info-item">{{ taskType }}</span>
        </li>
        <li>
          <span class="database_info-title">名称：</span><span class="database_info-item">{{
            databaseInfoValue.source.dataSourceName
          }}</span>
        </li>
        <li>
          <span class="database_info-title">ip端口：</span><span class="database_info-item">{{
            `${databaseInfoValue.source.ip}:${databaseInfoValue.source.port}`
          }}</span>
        </li>
        <li>
          <span class="database_info-title">用户名：</span><span class="database_info-item">{{
            databaseInfoValue.source.uname
          }}</span>
          <span class="databaseInfo_text" @click="perViewInfo('source')">
            测试连接
          </span>
        </li>
      </ul>
      <el-collapse
        v-if="leftWidth >= fixedWidth && sourceDdl"
        v-model="sourceActiveNames"
        accordion
      >
        <el-collapse-item title="SQL" name="1">
          <div>
            <CodeEditor
              :editor-hight="
                sourceDdl.lineNum * 22 > 300 ? 300 : sourceDdl.lineNum * 22
              "
              read-only
              :code-data="sourceDdl.ddl"
              :value-font-size="12"
            />
          </div>
        </el-collapse-item>
        <el-collapse-item title="会话历史" name="2">
          <ul class="history_box">
            <li
              v-for="(f, i) in historyQuestioning"
              :key="f.message"
              @click="previewMessage(i)"
            >
              <el-tooltip
                popper-class="ai-history-tooltip"
                effect="dark"
                :content="f.title"
                placement="top-start"
              >
                <span class="history_title">{{ f.title }}</span>
              </el-tooltip>
              <span>#{{ i + 1 }}</span>
            </li>
          </ul>
        </el-collapse-item>
      </el-collapse>
      <div
        class="dargLine"
        style="right: 0"
        @mousedown="(e) => dragStart(e, 'left')"
      />
    </div>
    <div class="content" :style="{ width: AiContentWidth + 'px' }">
      <Chat
        v-if="taskType && databaseInfo"
        :task-type="taskType"
        :database-info="databaseInfo"
        :execute-sql-data="executeSqlData"
        :sink-ddl="sinkDdl.ddl"
        @getHistory-event="getHistory"
        @setSinkDdl="setSinkDdl"
      />
    </div>
    <div class="chat-left boxShadow" :style="{ width: rightWidth + 'px' }">
      <div class="contract">
        <div
          class="svg_box"
          :style="{
            transform: rightWidth >= fixedWidth ? 'rotate(180deg)' : '',
          }"
          @click="handleChangeRightWidth"
        >
          <svg
            width="20"
            height="20"
            viewBox="0 0 17 17"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <g opacity="0.6">
              <path
                d="M5.35156 8.5H15.3516"
                stroke="#333333"
                stroke-width="1.5"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <path
                d="M9.09347 13.1559L4.4375 8.49981L9.09347 3.84375"
                stroke="#333333"
                stroke-width="1.5"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <rect
                x="0.351562"
                y="2.5"
                width="1.5"
                height="12"
                rx="0.75"
                fill="#333333"
              />
            </g>
          </svg>
        </div>
        <p v-if="rightWidth >= fixedWidth" class="contract_title">目标端信息</p>
      </div>
      <ul
        v-if="rightWidth >= fixedWidth && databaseInfoValue.sink"
        class="database_info"
      >
        <li>
          <span class="database_info-title">名称：</span><span class="database_info-item">{{
            databaseInfoValue.sink.dataSourceName
          }}</span>
        </li>
        <li>
          <span class="database_info-title">ip端口：</span><span class="database_info-item">{{
            `${databaseInfoValue.sink.ip}:${databaseInfoValue.sink.port}`
          }}</span>
        </li>
        <li>
          <span class="database_info-title">用户名：</span><span class="database_info-item">{{
            databaseInfoValue.sink.uname
          }}</span>
          <span class="databaseInfo_text" @click="perViewInfo('sink')">
            测试连接
          </span>
        </li>
      </ul>
      <el-collapse
        v-if="rightWidth >= fixedWidth && sinkDdl"
        v-model="sinkActiveNames"
        accordion
      >
        <el-collapse-item title="SQL" name="1">
          <div>
            <CodeEditor
              :key="sinkDdl.key"
              :editor-hight="
                sinkDdl.lineNum * 25 > 320 ? 320 : sinkDdl.lineNum * 25
              "
              :code-data="sinkDdl.ddl"
              :value-font-size="12"
              :change-code="changeCodeInput"
            />
          </div>
        </el-collapse-item>
      </el-collapse>
      <div
        class="dargLine"
        style="left: 0"
        @mousedown="(e) => dragStart(e, 'right')"
      />
    </div>

    <el-dialog
      v-if="NextdataDialog"
      title="数据源信息"
      width="800px"
      :visible.sync="NextdataDialog"
    >
      <databaseView :form="databaseInfoTypeValue" />
      <div slot="footer" class="dialog-footer">
        <el-button @click="testConnect">测试连接</el-button>
        <el-button
          type="primary"
          style="margin-left: 10px"
          @click="NextdataDialog = false"
        >确 定</el-button>
      </div>
    </el-dialog>

    <el-dialog
      v-if="previewMessageValue"
      :title="
        previewMessageValue.title.length > 15
          ? `${previewMessageValue.title.slice(0, 15)}...`
          : previewMessageValue.title
      "
      width="800px"
      :visible.sync="previewMessageVisible"
    >
      <div style="max-height: 500px; overflow-y: auto">
        <div style="text-align: right">
          <p class="message-content">{{ previewMessageValue.history.user }}</p>
        </div>
        <Markdown
          ref="mark"
          :source="previewMessageValue.history.ai"
          :execute-sql-data="executeSqlData"
        />
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button
          type="primary"
          @click="previewMessageVisible = false"
        >确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import Chat from './components/chat.vue'
import { getAiList } from '@/api/console/belfAi'
import databaseView from './components/databaseView.vue'
import { getDataTaskconf } from '@/api/console/dataTaskconf.js'
import Markdown from '@/components/marckdown'
import { getDatasourceInfo, databaseCheck } from '@/api/console/datasourceInfo'
import CodeEditor from '@/components/CodeEditor/index.vue'

export default {
  name: 'MigrationReportAi',
  components: {
    Chat,
    databaseView,
    // eslint-disable-next-line vue/no-unused-components
    editor: require('vue2-ace-editor'),
    Markdown,
    CodeEditor
  },
  dicts: ['transfer_result_object_type'],
  data() {
    return {
      fixedWidth: null,
      leftWidth: null,
      rightWidth: null,
      AiContentWidth: null,
      previewCode: false,
      aiModel: 'Doubao-lite-32k',
      aiModelList: [],
      taskType: null,
      databaseInfo: null,
      NextdataDialog: false,
      databaseInfoValue: {},
      sinkObjectName: null,
      ddl: null,
      historyQuestioning: [],
      executeSqlData: null,
      previewMessageVisible: false,
      previewMessageValue: null,
      sourceDdl: '',
      sinkDdl: '',
      sourceActiveNames: '1',
      sinkActiveNames: '1'
    }
  },
  created() {
    this.fixedWidth = window.innerWidth * 0.25
    this.leftWidth = window.innerWidth * 0.25
    this.rightWidth = window.innerWidth * 0.25
    this.AiContentWidth = window.innerWidth * 0.5
  },
  async mounted() {
    const { type, taskId, sinkObjectName, sinkDdl, sourceDdl } = JSON.parse(
      localStorage.getItem('migrationReportAi')
    )
    this.sinkObjectName = sinkObjectName
    let res = await this.getDicts('transfer_result_object_type')
    this.taskType = res.data.filter((f) =>
      f.dictValue.includes(type)
    )[0].dictLabel
    res = await getDataTaskconf({
      id: taskId
    })
    this.databaseInfo = res.data
    res = await getDatasourceInfo({
      id: this.databaseInfo[`sourceId`]
    })
    this.databaseInfoValue.source = res.data
    res = await getDatasourceInfo({
      id: this.databaseInfo[`sinkId`]
    })
    this.databaseInfoValue.sink = res.data
    this.sourceDdl = {
      ddl: this.sqlFormatter.format(sourceDdl || ''),
      lineNum:
        sourceDdl && sourceDdl.length > 0
          ? (sourceDdl.match(/\n/g) || []).length
          : 2
    }
    this.sinkDdl = {
      ddl: this.sqlFormatter.format(sinkDdl || ''),
      lineNum:
        sinkDdl && sinkDdl.length > 0 ? (sinkDdl.match(/\n/g) || []).length : 2
    }
    if (sourceDdl && sourceDdl.length > 0) {
      this.ddl = sourceDdl
      this.executeSqlData = {
        databaseName: this.databaseInfo.sourceName,
        datasourceId: this.databaseInfo.sourceId
      }
    } else {
      this.ddl = sinkDdl
      this.executeSqlData = {
        databaseName: this.databaseInfo.sinkName,
        datasourceId: this.databaseInfo.sinkId
      }
    }
    res = await getAiList()
    Object.keys(this.sort(res)).forEach((f) => {
      this.aiModelList.push({
        label: `${res[f]}(${f})`,
        value: f
      })
    })
  },
  methods: {
    changeCodeInput(e) {
      this.sinkDdl.ddl = e
    },
    dragStart(e, type) {
      const that = this
      e.preventDefault()

      // 保存鼠标按下时的位置
      var startX = e.clientX
      // 保存当前元素宽度，以便拖动时更新
      var startWidth = that[`${type}Width`]

      // 绑定拖动事件
      document.onmousemove = function(e) {
        // 计算移动后的位置和原位置之间的差值
        var diffX =
          type === 'left'
            ? startWidth + (e.clientX - startX)
            : startWidth - (e.clientX - startX)

        if (diffX <= that.fixedWidth) {
          that[`${type}Width`] = that.fixedWidth
          return
        }
        that[`${type}Width`] = diffX
      }

      // 绑定拖动结束事件
      document.onmouseup = function() {
        document.onmousemove = null
        document.onmouseup = null
      }
    },
    setSinkDdl(ddl) {
      this.sinkDdl = {
        ddl,
        key: Math.random(),
        lineNum: (ddl.match(/\n/g) || []).length
      }
    },
    perViewInfo(type) {
      this.NextdataDialog = true
      this.databaseInfoTypeValue = this.databaseInfoValue[type]
    },
    handleChangeLeftWidth() {
      this.leftWidth =
        this.leftWidth === this.fixedWidth ? 40 : this.fixedWidth
      this.gainAiCurrentWidth()
    },
    handleChangeRightWidth() {
      this.rightWidth =
        this.rightWidth === this.fixedWidth ? 40 : this.fixedWidth
      this.gainAiCurrentWidth()
    },
    gainAiCurrentWidth() {
      this.AiContentWidth =
        window.innerWidth - this.rightWidth - this.leftWidth
    },
    previewMessage(i) {
      this.previewMessageValue = this.historyQuestioning[i]
      this.previewMessageVisible = true
    },
    sort(data) {
      const sortedData = Object.entries(data).sort((a, b) => {
        const [, valueA] = a
        const [, valueB] = b
        return valueA.split('-')[0].localeCompare(valueB.split('-')[0])
      })
      const result = Object.fromEntries(sortedData)
      return result
    },
    copyDdl() {
      const dom = document.createElement('input')
      dom.value = this.ddl
      document.body.appendChild(dom)
      dom.select()
      document.execCommand('copy')
      document.body.removeChild(dom)
      this.$message.success('复制成功')
    },
    editorInit() {
      // 初始化
      require('brace/ext/language_tools')
      require('brace/ext/beautify')
      require('brace/ext/error_marker')
      require('brace/ext/searchbox')
      require('brace/ext/split')
      require('brace/snippets/sql')
      require('brace/mode/sql')
      require('brace/theme/dracula')
    },
    getHistory(history) {
      const arr = []
      history.forEach((f, i) => {
        // console.log();
        if (i % 2 !== 0) {
          if (f.type === 'error') {
            return
          } else {
            arr.unshift({
              title: history[i - 1].message,
              history: {
                user: history[i - 1].message,
                ai: f.message
              }
            })
          }
        }
      })
      this.historyQuestioning = arr
    },
    // handleDatabaseInfo(type) {

    // },
    async testConnect() {
      const {
        type,
        ip,
        port,
        uname,
        pwd,
        databaseName,
        version,
        encoding,
        useUnicode,
        connectTimeout,
        socketTimeout,
        driver,
        url
      } = this.databaseInfoTypeValue
      const response = await databaseCheck({
        type,
        ip,
        port,
        uname,
        pwd,
        databaseName,
        version,
        encoding,
        useUnicode,
        connectTimeout,
        socketTimeout,
        driver,
        url
      })
      if (response.data.code === 200) {
        this.$message({
          message: '连接成功',
          type: 'success'
        })
        this.form.testStatus = 0
      } else {
        this.form.testStatus = 1
        this.$message.error('连接失败')
      }
    }
  }
}
</script>

<style scoped lang="scss">
.main {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: rgb(245, 247, 250);
  display: flex;
  justify-content: space-between;

  * {
    margin: 0;
    list-style-type: none;
  }

  .boxShadow {
    box-shadow: -10px 0 10px -5px rgba(192, 192, 192, 0.3) !important;
  }

  .history_box {
    list-style-type: none;
    padding: 0;
    margin: 0;

    li {
      font-weight: 500;
      font-size: 13px;
      width: 95%;
      background: rgb(243, 244, 246);
      padding: 5px;
      border-radius: 3px;
      color: #222;
      margin: 8px 0;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: space-around;
      p {
        text-overflow: ellipsis;
        overflow: hidden;
        white-space: nowrap;
        width: 90%;
        margin: 0;
      }
    }
  }

  .message-content {
    text-align: left;
    word-break: break-word;
    white-space: pre-wrap;
    border-radius: 15px;
    padding: 5px 10px;
    font-size: 14px;
    display: inline-block;
    width: auto;
    color: #121512;
    background-color: rgb(245, 245, 245);
    margin: 0;
  }

  .chat-left {
    padding: 22px 12px 0px 12px;
    box-sizing: border-box;
    position: relative;
    display: flex;
    flex-direction: column;
    background: #fff;
    height: 100%;
    box-shadow: 10px 0 10px -5px rgba(192, 192, 192, 0.3);

    .dargLine {
      position: absolute;
      height: 100%;
      width: 3px;
      cursor: e-resize;
    }

    .contract {
      display: flex;
      align-items: center;
      justify-content: space-between;

      .contract_title {
        font-size: 20px;
        font-weight: 600;
        position: relative;
        top: 2px;
        white-space: nowrap;
      }

      .svg_box {
        float: right;
        font-size: 17px;
        color: #333333;
        height: 20px;
        cursor: pointer;
      }
    }
    .database_info {
      padding: 5px 0;
      margin: 10px 0;

      li {
        margin: 10px 0;
        font-size: 14px;
        font-weight: 600;

        .database_info-item {
          font-family: "sim";
          font-size: 12px;
          color: #333;
          margin: 5px 0;
          font-weight: 500;
        }
        .database_info-title {
          width: 38%;
          display: inline-block;
        }

        .databaseInfo_text {
          color: blue;
          font-size: 12px;
          cursor: pointer;
          float: right;
        }
      }
    }

    .history_title {
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      width: 85%;
    }
  }

  .content {
    padding: 5px 15px;
  }
}
</style>

<style scoped>
::v-deep .el-tabs--border-card {
  height: 100%;
}

::v-deep .el-tabs__content,
.el-tab-pane {
  height: 100%;
}
</style>

<style>
.ai-history-tooltip {
  max-width: 500px !important;
  max-height: 500px !important;
  overflow: auto;
}
</style>
